import * as fs from 'fs-extra';
import { format, replaceToUpperCase } from '../util/lang';
import { Data, Paths } from '../interface'

interface Params {
  outDir: string;
  fileName: string;
  fileType: string;
  servicesHeader: string;
  interfaces: string[];
}

const setTsName = (item: Data, action: string) => {
  let { formatUrl } = item;

  formatUrl = formatUrl.split('?')[0];
  const strArr = formatUrl.split('/').map(item => {
    return item.replace(/{|}/g, '').toLocaleLowerCase().split('_').map(subItem => {
      return subItem.replace(/:/, '').replace(/^\S/, s => s.toUpperCase());
    });
  });
  const result = [].concat(...[...strArr].splice(2));
  return `${action.replace(/^\S/, s => s.toUpperCase())}${result.join('')}`;
}

// 方法名
const setActionName = (item: Data, key: string) => {
  let { formatUrl } = item;

  formatUrl = formatUrl.split('?')[0];
  const strArr = formatUrl.split('/').map(item => {
    return item.replace(/{|}/g, '').toLocaleLowerCase().split(/_|-/).map(subItem => {
      return subItem.replace(/:/, '').replace(/^\S/, s => s.toUpperCase());
    });
  });
  const result = [].concat(...[...strArr].splice(1));
  return `${key}${result.join('')}`;
}

// const setParamDesc = (data: Parameter[]) => {
//   let result = ``;

//   data.forEach((item: Parameter) => {
//     result += `* @param {${item.type}} params.${item.name}`;
//   })

//   return result;
// }

// 方法描述
// const setActionDesc = (item: Data) => {
//   const { description, parameters } = item;
//   const headerParams = [];
//   const bodyParams = [];
//   const pathParams = [];

//   parameters.map((item: Parameter) => {
//     switch (item.in) {
//       case 'header':
//         headerParams.push(item);
//         break;
//       case 'body':
//         bodyParams.push(item);
//         break;
//       case 'path':
//         pathParams.push(item);
//         break;
//       default:;
//     }
//   });

//   if (bodyParams.length === 0 && pathParams.length === 0) {
//     return `
//       /**
//        * @desc ${description}
//        */
//     `
//   }

//   if (pathParams.length) {
//     return `
//       /**
//        * @desc ${description}
//        * @param {object} params
//        ${setParamDesc(pathParams)}
//        ${setParamDesc(bodyParams)}
//        */
//     `
//   }

//   return `
//     /**
//      * @desc ${description}
//      * @param {object} params
//      ${setParamDesc(bodyParams)}
//      */
//   `
// }


const setParams = (urlParams: string[], params: Params, request: string, response: string, responseType: string) => {
  const { fileType, fileName, interfaces = [] } = params;
  function setUrlParams() {
    if (urlParams.length > 0) {
      return `${urlParams.join(', ')}, `;
    }
    return '';
  }
  const ps = urlParams.length ? `{ ${setUrlParams()}...params }` : `params`;
  // const interfaceName = interfaces.includes(request) ? `${ps}: ${fileName}.${request}` : `${ps}={}`;
  
  // if (fileType === 'ts') {
  //   if (response === '') {
  //     return `(${interfaceName}, config:RequestConfig = {}):ServicePromise`;
  //   }
  //   return `(${interfaceName}, config:RequestConfig = {}):ServicePromise<${fileName}.${response}${responseType ? '[]' : ''}>`;
  // }
  return `(${ps}={}, config={})`;
}

const setAjax = (item: Data, key: string, action: string, params: Params) => {
  const modify = ['post', 'put', 'patch'];
  const { description, summary, parameters = [], consumes = [], responses } = item;
  const actionName = setActionName(item, key);
  const request = setTsName(item, action);
  let response = '';
  let responseType = '';
  let urlParams = [];
  let url = item.url;
  let method = key;

  // if (responses && responses[200].schema) {
  //   if (responses[200].schema.type === 'array') {
  //     response = replaceToUpperCase(responses[200].schema.items.$ref);
  //     responseType = 'array';
  //   } else {
  //     const rp = replaceToUpperCase(responses[200].schema.$ref);
  //     response = params.interfaces.includes(rp) ? rp : ''; 
  //   }
  // }
  
  // multipart/form-data 格式的时候调用ax/service封装的upload
  // application/x-www-form-urlencoded且是post请求
  // if (consumes.length && (consumes[0] === 'multipart/form-data' || (consumes[0] === 'application/x-www-form-urlencoded' && key === 'post'))) {
  //   method = 'upload';
  // }

  parameters.map(item => {
    if (item.in === 'path') {
      urlParams.push(item.name);
      url = url.replace(`{${item.name}}`, '${' + item.name + '}');
      url = url.replace(`:${item.name}`, '${' + item.name + '}');
    }
  });

  if (modify.indexOf(key) !== -1) {
    return `
/**
 * @desc ${description || summary}
 */
export function ${actionName} ${setParams(urlParams, params, request, response, responseType)} => {
  return service.${method}(@@${url}@@, params, config);
}
    `
  }

  return `
/**
 * @desc ${description || summary}
 */
export function ${actionName} ${setParams(urlParams, params, request, response, responseType)} => {
  return service.${method}(@@${url}@@, { ...config, params });
}
  `;
}


const setActionContent = (data: Paths, params: Params) => {
  let result = '';
  Object.keys(data).map(el => {
    Object.keys(data[el]).map(key => {
      const item = data[el][key];
      const action = Object.keys(data[el]).length > 1 ? key : ''
      result += setAjax(item, key.toLowerCase(), action, params).replace(/@@/g, '`');
    });
  })
  return result;
}

const setServicesHeader = (params: Params) => {
  const { fileType, servicesHeader } = params;
  // if (fileType === 'ts') {
  //   return `
  //     import { ServicePromise, RequestConfig } from '@ax/service/lib/interface';
  //     ${servicesHeader}
  //   `
  // }
  return servicesHeader;
}

const setServiceContent = (data: Paths, params: Params) => {

  return `
/**
 * ax-snippets 生成的 Service
 */    
${setServicesHeader(params)}   
${setActionContent(data, params)}
  `;
}

export function serviceGenerate(data: Paths, params: Params) {
  const { outDir, fileType = 'ts', fileName } = params;
  const value = setServiceContent(data, params);
  return new Promise<void>((resolve, reject) => {
    fs.outputFile(`${outDir}/${fileName}.${fileType}`, format(value), err => {
      if (err) {
        reject(err);
      }
      console.log(`Generate ${fileName}.ts success!`)
      resolve();
    });
  })
}